// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

#include <ParallelCoordinatesAttributes.h>
#include <DataNode.h>

//
// Enum conversion methods for ParallelCoordinatesAttributes::FocusRendering
//

static const char *FocusRendering_strings[] = {
"IndividualLines", "BinsOfConstantColor", "BinsColoredByPopulation"
};

std::string
ParallelCoordinatesAttributes::FocusRendering_ToString(ParallelCoordinatesAttributes::FocusRendering t)
{
    int index = int(t);
    if(index < 0 || index >= 3) index = 0;
    return FocusRendering_strings[index];
}

std::string
ParallelCoordinatesAttributes::FocusRendering_ToString(int t)
{
    int index = (t < 0 || t >= 3) ? 0 : t;
    return FocusRendering_strings[index];
}

bool
ParallelCoordinatesAttributes::FocusRendering_FromString(const std::string &s, ParallelCoordinatesAttributes::FocusRendering &val)
{
    val = ParallelCoordinatesAttributes::IndividualLines;
    for(int i = 0; i < 3; ++i)
    {
        if(s == FocusRendering_strings[i])
        {
            val = (FocusRendering)i;
            return true;
        }
    }
    return false;
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::ParallelCoordinatesAttributes
//
// Purpose:
//   Init utility for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void ParallelCoordinatesAttributes::Init()
{
    drawLines = true;
    drawContext = true;
    contextGamma = 2;
    contextNumPartitions = 128;
    drawLinesOnlyIfExtentsOn = true;
    unifyAxisExtents = false;
    linesNumPartitions = 512;
    focusGamma = 4;
    drawFocusAs = BinsOfConstantColor;

    ParallelCoordinatesAttributes::SelectAll();
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::ParallelCoordinatesAttributes
//
// Purpose:
//   Copy utility for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void ParallelCoordinatesAttributes::Copy(const ParallelCoordinatesAttributes &obj)
{
    scalarAxisNames = obj.scalarAxisNames;
    visualAxisNames = obj.visualAxisNames;
    extentMinima = obj.extentMinima;
    extentMaxima = obj.extentMaxima;
    drawLines = obj.drawLines;
    linesColor = obj.linesColor;
    drawContext = obj.drawContext;
    contextGamma = obj.contextGamma;
    contextNumPartitions = obj.contextNumPartitions;
    contextColor = obj.contextColor;
    drawLinesOnlyIfExtentsOn = obj.drawLinesOnlyIfExtentsOn;
    unifyAxisExtents = obj.unifyAxisExtents;
    linesNumPartitions = obj.linesNumPartitions;
    focusGamma = obj.focusGamma;
    drawFocusAs = obj.drawFocusAs;

    ParallelCoordinatesAttributes::SelectAll();
}

// Type map format string
const char *ParallelCoordinatesAttributes::TypeMapFormatString = PARALLELCOORDINATESATTRIBUTES_TMFS;
const AttributeGroup::private_tmfs_t ParallelCoordinatesAttributes::TmfsStruct = {PARALLELCOORDINATESATTRIBUTES_TMFS};


// ****************************************************************************
// Method: ParallelCoordinatesAttributes::ParallelCoordinatesAttributes
//
// Purpose:
//   Default constructor for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

ParallelCoordinatesAttributes::ParallelCoordinatesAttributes() :
    AttributeSubject(ParallelCoordinatesAttributes::TypeMapFormatString),
    linesColor(128, 0, 0), contextColor(0, 220, 0)
{
    ParallelCoordinatesAttributes::Init();
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::ParallelCoordinatesAttributes
//
// Purpose:
//   Constructor for the derived classes of ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

ParallelCoordinatesAttributes::ParallelCoordinatesAttributes(private_tmfs_t tmfs) :
    AttributeSubject(tmfs.tmfs),
    linesColor(128, 0, 0), contextColor(0, 220, 0)
{
    ParallelCoordinatesAttributes::Init();
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::ParallelCoordinatesAttributes
//
// Purpose:
//   Copy constructor for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

ParallelCoordinatesAttributes::ParallelCoordinatesAttributes(const ParallelCoordinatesAttributes &obj) :
    AttributeSubject(ParallelCoordinatesAttributes::TypeMapFormatString)
{
    ParallelCoordinatesAttributes::Copy(obj);
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::ParallelCoordinatesAttributes
//
// Purpose:
//   Copy constructor for derived classes of the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

ParallelCoordinatesAttributes::ParallelCoordinatesAttributes(const ParallelCoordinatesAttributes &obj, private_tmfs_t tmfs) :
    AttributeSubject(tmfs.tmfs)
{
    ParallelCoordinatesAttributes::Copy(obj);
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::~ParallelCoordinatesAttributes
//
// Purpose:
//   Destructor for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

ParallelCoordinatesAttributes::~ParallelCoordinatesAttributes()
{
    // nothing here
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::operator =
//
// Purpose:
//   Assignment operator for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

ParallelCoordinatesAttributes&
ParallelCoordinatesAttributes::operator = (const ParallelCoordinatesAttributes &obj)
{
    if (this == &obj) return *this;

    ParallelCoordinatesAttributes::Copy(obj);

    return *this;
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::operator ==
//
// Purpose:
//   Comparison operator == for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
ParallelCoordinatesAttributes::operator == (const ParallelCoordinatesAttributes &obj) const
{
    // Create the return value
    return ((scalarAxisNames == obj.scalarAxisNames) &&
            (visualAxisNames == obj.visualAxisNames) &&
            (extentMinima == obj.extentMinima) &&
            (extentMaxima == obj.extentMaxima) &&
            (drawLines == obj.drawLines) &&
            (linesColor == obj.linesColor) &&
            (drawContext == obj.drawContext) &&
            (contextGamma == obj.contextGamma) &&
            (contextNumPartitions == obj.contextNumPartitions) &&
            (contextColor == obj.contextColor) &&
            (drawLinesOnlyIfExtentsOn == obj.drawLinesOnlyIfExtentsOn) &&
            (unifyAxisExtents == obj.unifyAxisExtents) &&
            (linesNumPartitions == obj.linesNumPartitions) &&
            (focusGamma == obj.focusGamma) &&
            (drawFocusAs == obj.drawFocusAs));
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::operator !=
//
// Purpose:
//   Comparison operator != for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
ParallelCoordinatesAttributes::operator != (const ParallelCoordinatesAttributes &obj) const
{
    return !(this->operator == (obj));
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::TypeName
//
// Purpose:
//   Type name method for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const std::string
ParallelCoordinatesAttributes::TypeName() const
{
    return "ParallelCoordinatesAttributes";
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::CopyAttributes
//
// Purpose: Sets the attributes from another attribute group
//
// Programmer: Jeremy Meredith
// Creation:   January 31, 2008
//
// Modifications:
//    Jeremy Meredith, Fri Feb  1 17:56:21 EST 2008
//    Added support for axis restrictions.
//
//    Jeremy Meredith, Thu Feb  7 17:45:11 EST 2008
//    Allow empty axis name list; this happens for array variables.
//
//    Jeremy Meredith, Fri Feb 15 13:16:46 EST 2008
//    Renamed orderedAxisNames to scalarAxisNames to distinguish these
//    as names of actual scalars instead of just display names.  Added
//    visualAxisNames.
//
// ****************************************************************************
bool
ParallelCoordinatesAttributes::CopyAttributes(const AttributeGroup *atts)
{
    bool retval = false;

    if(TypeName() == atts->TypeName())
    {
        // Call assignment operator.
        const ParallelCoordinatesAttributes *tmp =
            (const ParallelCoordinatesAttributes *)atts;
        *this = *tmp;
        retval = true;
    }
    else if (atts->TypeName() == "AxisRestrictionAttributes")
    {
        const AxisRestrictionAttributes *ar =
            (const AxisRestrictionAttributes *)atts;

        if (scalarAxisNames.size() == 0)
        {
            visualAxisNames = ar->GetNames();
            extentMinima = ar->GetMinima();
            extentMaxima = ar->GetMaxima();
        }
        else
        {
            for (size_t i=0; i<extentMinima.size(); i++)
            {
                extentMinima[i] = ar->GetMinima()[i];
                extentMaxima[i] = ar->GetMaxima()[i];
            }
        }
        SelectVisualAxisNames();
        SelectExtentMinima();
        SelectExtentMaxima();

        retval = true;
    }
    return retval;
}

// ****************************************************************************
//  Method:  ParallelCoordinatesAttributes::CreateCompatible
//
//  Purpose:
//    Creates an object of the specified type initialized with the
//    attributes from this object.
//
//  Arguments:
//    tname : The typename of the object that we want to create.
//
//  Returns:    A new object of the type specified by tname or 0.
//
//  Programmer:  Jeremy Meredith
//  Creation:    February  8, 2008
//
//  Modifications:
//    Jeremy Meredith, Fri Feb 15 13:13:56 EST 2008
//    Added better support for axis names.
//
// ****************************************************************************
AttributeSubject *
ParallelCoordinatesAttributes::CreateCompatible(const std::string &tname) const
{
    AttributeSubject *retval = 0;

    if(TypeName() == tname)
    {
        retval = new ParallelCoordinatesAttributes(*this);
    }
    else if (tname == "AxisRestrictionAttributes" ||
             tname == "ThresholdAttributes")
    {
        // Note: my hope was that we could update the plot attributes
        // and have it connect with a threshold tool in another window.
        // Unfortunately, CreateCompatible("ThresholdAttributes") isn't
        // called, so there's a missing path issue.  We could probably
        // get rid of the support for Threshold here.
        AxisRestrictionAttributes *ar = new AxisRestrictionAttributes;

        ar->SetNames(visualAxisNames);
        ar->SetMinima(extentMinima);
        ar->SetMaxima(extentMaxima);

        if (tname == "AxisRestrictionAttributes")
        {
            retval = ar;
        }
        else
        {
            retval = ar->CreateCompatible(tname);
            delete ar;
        }
    }

    return retval;
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::NewInstance
//
// Purpose:
//   NewInstance method for the ParallelCoordinatesAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeSubject *
ParallelCoordinatesAttributes::NewInstance(bool copy) const
{
    AttributeSubject *retval = 0;
    if(copy)
        retval = new ParallelCoordinatesAttributes(*this);
    else
        retval = new ParallelCoordinatesAttributes;

    return retval;
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::SelectAll
//
// Purpose:
//   Selects all attributes.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
ParallelCoordinatesAttributes::SelectAll()
{
    Select(ID_scalarAxisNames,          (void *)&scalarAxisNames);
    Select(ID_visualAxisNames,          (void *)&visualAxisNames);
    Select(ID_extentMinima,             (void *)&extentMinima);
    Select(ID_extentMaxima,             (void *)&extentMaxima);
    Select(ID_drawLines,                (void *)&drawLines);
    Select(ID_linesColor,               (void *)&linesColor);
    Select(ID_drawContext,              (void *)&drawContext);
    Select(ID_contextGamma,             (void *)&contextGamma);
    Select(ID_contextNumPartitions,     (void *)&contextNumPartitions);
    Select(ID_contextColor,             (void *)&contextColor);
    Select(ID_drawLinesOnlyIfExtentsOn, (void *)&drawLinesOnlyIfExtentsOn);
    Select(ID_unifyAxisExtents,         (void *)&unifyAxisExtents);
    Select(ID_linesNumPartitions,       (void *)&linesNumPartitions);
    Select(ID_focusGamma,               (void *)&focusGamma);
    Select(ID_drawFocusAs,              (void *)&drawFocusAs);
}

///////////////////////////////////////////////////////////////////////////////
// Persistence methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::CreateNode
//
// Purpose:
//   This method creates a DataNode representation of the object so it can be saved to a config file.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
ParallelCoordinatesAttributes::CreateNode(DataNode *parentNode, bool completeSave, bool forceAdd)
{
    if(parentNode == 0)
        return false;

    ParallelCoordinatesAttributes defaultObject;
    bool addToParent = false;
    // Create a node for ParallelCoordinatesAttributes.
    DataNode *node = new DataNode("ParallelCoordinatesAttributes");

    if(completeSave || !FieldsEqual(ID_scalarAxisNames, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("scalarAxisNames", scalarAxisNames));
    }

    if(completeSave || !FieldsEqual(ID_visualAxisNames, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("visualAxisNames", visualAxisNames));
    }

    if(completeSave || !FieldsEqual(ID_extentMinima, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("extentMinima", extentMinima));
    }

    if(completeSave || !FieldsEqual(ID_extentMaxima, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("extentMaxima", extentMaxima));
    }

    if(completeSave || !FieldsEqual(ID_drawLines, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("drawLines", drawLines));
    }

        DataNode *linesColorNode = new DataNode("linesColor");
        if(linesColor.CreateNode(linesColorNode, completeSave, true))
        {
            addToParent = true;
            node->AddNode(linesColorNode);
        }
        else
            delete linesColorNode;
    if(completeSave || !FieldsEqual(ID_drawContext, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("drawContext", drawContext));
    }

    if(completeSave || !FieldsEqual(ID_contextGamma, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("contextGamma", contextGamma));
    }

    if(completeSave || !FieldsEqual(ID_contextNumPartitions, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("contextNumPartitions", contextNumPartitions));
    }

        DataNode *contextColorNode = new DataNode("contextColor");
        if(contextColor.CreateNode(contextColorNode, completeSave, true))
        {
            addToParent = true;
            node->AddNode(contextColorNode);
        }
        else
            delete contextColorNode;
    if(completeSave || !FieldsEqual(ID_drawLinesOnlyIfExtentsOn, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("drawLinesOnlyIfExtentsOn", drawLinesOnlyIfExtentsOn));
    }

    if(completeSave || !FieldsEqual(ID_unifyAxisExtents, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("unifyAxisExtents", unifyAxisExtents));
    }

    if(completeSave || !FieldsEqual(ID_linesNumPartitions, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("linesNumPartitions", linesNumPartitions));
    }

    if(completeSave || !FieldsEqual(ID_focusGamma, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("focusGamma", focusGamma));
    }

    if(completeSave || !FieldsEqual(ID_drawFocusAs, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("drawFocusAs", FocusRendering_ToString(drawFocusAs)));
    }


    // Add the node to the parent node.
    if(addToParent || forceAdd)
        parentNode->AddNode(node);
    else
        delete node;

    return (addToParent || forceAdd);
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::SetFromNode
//
// Purpose:
//   This method sets attributes in this object from values in a DataNode representation of the object.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
ParallelCoordinatesAttributes::SetFromNode(DataNode *parentNode)
{
    if(parentNode == 0)
        return;

    DataNode *searchNode = parentNode->GetNode("ParallelCoordinatesAttributes");
    if(searchNode == 0)
        return;

    DataNode *node;
    if((node = searchNode->GetNode("scalarAxisNames")) != 0)
        SetScalarAxisNames(node->AsStringVector());
    if((node = searchNode->GetNode("visualAxisNames")) != 0)
        SetVisualAxisNames(node->AsStringVector());
    if((node = searchNode->GetNode("extentMinima")) != 0)
        SetExtentMinima(node->AsDoubleVector());
    if((node = searchNode->GetNode("extentMaxima")) != 0)
        SetExtentMaxima(node->AsDoubleVector());
    if((node = searchNode->GetNode("drawLines")) != 0)
        SetDrawLines(node->AsBool());
    if((node = searchNode->GetNode("linesColor")) != 0)
        linesColor.SetFromNode(node);
    if((node = searchNode->GetNode("drawContext")) != 0)
        SetDrawContext(node->AsBool());
    if((node = searchNode->GetNode("contextGamma")) != 0)
        SetContextGamma(node->AsFloat());
    if((node = searchNode->GetNode("contextNumPartitions")) != 0)
        SetContextNumPartitions(node->AsInt());
    if((node = searchNode->GetNode("contextColor")) != 0)
        contextColor.SetFromNode(node);
    if((node = searchNode->GetNode("drawLinesOnlyIfExtentsOn")) != 0)
        SetDrawLinesOnlyIfExtentsOn(node->AsBool());
    if((node = searchNode->GetNode("unifyAxisExtents")) != 0)
        SetUnifyAxisExtents(node->AsBool());
    if((node = searchNode->GetNode("linesNumPartitions")) != 0)
        SetLinesNumPartitions(node->AsInt());
    if((node = searchNode->GetNode("focusGamma")) != 0)
        SetFocusGamma(node->AsFloat());
    if((node = searchNode->GetNode("drawFocusAs")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 3)
                SetDrawFocusAs(FocusRendering(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            FocusRendering value;
            if(FocusRendering_FromString(node->AsString(), value))
                SetDrawFocusAs(value);
        }
    }
}

///////////////////////////////////////////////////////////////////////////////
// Set property methods
///////////////////////////////////////////////////////////////////////////////

void
ParallelCoordinatesAttributes::SetScalarAxisNames(const stringVector &scalarAxisNames_)
{
    scalarAxisNames = scalarAxisNames_;
    Select(ID_scalarAxisNames, (void *)&scalarAxisNames);
}

void
ParallelCoordinatesAttributes::SetVisualAxisNames(const stringVector &visualAxisNames_)
{
    visualAxisNames = visualAxisNames_;
    Select(ID_visualAxisNames, (void *)&visualAxisNames);
}

void
ParallelCoordinatesAttributes::SetExtentMinima(const doubleVector &extentMinima_)
{
    extentMinima = extentMinima_;
    Select(ID_extentMinima, (void *)&extentMinima);
}

void
ParallelCoordinatesAttributes::SetExtentMaxima(const doubleVector &extentMaxima_)
{
    extentMaxima = extentMaxima_;
    Select(ID_extentMaxima, (void *)&extentMaxima);
}

void
ParallelCoordinatesAttributes::SetDrawLines(bool drawLines_)
{
    drawLines = drawLines_;
    Select(ID_drawLines, (void *)&drawLines);
}

void
ParallelCoordinatesAttributes::SetLinesColor(const ColorAttribute &linesColor_)
{
    linesColor = linesColor_;
    Select(ID_linesColor, (void *)&linesColor);
}

void
ParallelCoordinatesAttributes::SetDrawContext(bool drawContext_)
{
    drawContext = drawContext_;
    Select(ID_drawContext, (void *)&drawContext);
}

void
ParallelCoordinatesAttributes::SetContextGamma(float contextGamma_)
{
    contextGamma = contextGamma_;
    Select(ID_contextGamma, (void *)&contextGamma);
}

void
ParallelCoordinatesAttributes::SetContextNumPartitions(int contextNumPartitions_)
{
    contextNumPartitions = contextNumPartitions_;
    Select(ID_contextNumPartitions, (void *)&contextNumPartitions);
}

void
ParallelCoordinatesAttributes::SetContextColor(const ColorAttribute &contextColor_)
{
    contextColor = contextColor_;
    Select(ID_contextColor, (void *)&contextColor);
}

void
ParallelCoordinatesAttributes::SetDrawLinesOnlyIfExtentsOn(bool drawLinesOnlyIfExtentsOn_)
{
    drawLinesOnlyIfExtentsOn = drawLinesOnlyIfExtentsOn_;
    Select(ID_drawLinesOnlyIfExtentsOn, (void *)&drawLinesOnlyIfExtentsOn);
}

void
ParallelCoordinatesAttributes::SetUnifyAxisExtents(bool unifyAxisExtents_)
{
    unifyAxisExtents = unifyAxisExtents_;
    Select(ID_unifyAxisExtents, (void *)&unifyAxisExtents);
}

void
ParallelCoordinatesAttributes::SetLinesNumPartitions(int linesNumPartitions_)
{
    linesNumPartitions = linesNumPartitions_;
    Select(ID_linesNumPartitions, (void *)&linesNumPartitions);
}

void
ParallelCoordinatesAttributes::SetFocusGamma(float focusGamma_)
{
    focusGamma = focusGamma_;
    Select(ID_focusGamma, (void *)&focusGamma);
}

void
ParallelCoordinatesAttributes::SetDrawFocusAs(ParallelCoordinatesAttributes::FocusRendering drawFocusAs_)
{
    drawFocusAs = drawFocusAs_;
    Select(ID_drawFocusAs, (void *)&drawFocusAs);
}

///////////////////////////////////////////////////////////////////////////////
// Get property methods
///////////////////////////////////////////////////////////////////////////////

const stringVector &
ParallelCoordinatesAttributes::GetScalarAxisNames() const
{
    return scalarAxisNames;
}

stringVector &
ParallelCoordinatesAttributes::GetScalarAxisNames()
{
    return scalarAxisNames;
}

const stringVector &
ParallelCoordinatesAttributes::GetVisualAxisNames() const
{
    return visualAxisNames;
}

stringVector &
ParallelCoordinatesAttributes::GetVisualAxisNames()
{
    return visualAxisNames;
}

const doubleVector &
ParallelCoordinatesAttributes::GetExtentMinima() const
{
    return extentMinima;
}

doubleVector &
ParallelCoordinatesAttributes::GetExtentMinima()
{
    return extentMinima;
}

const doubleVector &
ParallelCoordinatesAttributes::GetExtentMaxima() const
{
    return extentMaxima;
}

doubleVector &
ParallelCoordinatesAttributes::GetExtentMaxima()
{
    return extentMaxima;
}

bool
ParallelCoordinatesAttributes::GetDrawLines() const
{
    return drawLines;
}

const ColorAttribute &
ParallelCoordinatesAttributes::GetLinesColor() const
{
    return linesColor;
}

ColorAttribute &
ParallelCoordinatesAttributes::GetLinesColor()
{
    return linesColor;
}

bool
ParallelCoordinatesAttributes::GetDrawContext() const
{
    return drawContext;
}

float
ParallelCoordinatesAttributes::GetContextGamma() const
{
    return contextGamma;
}

int
ParallelCoordinatesAttributes::GetContextNumPartitions() const
{
    return contextNumPartitions;
}

const ColorAttribute &
ParallelCoordinatesAttributes::GetContextColor() const
{
    return contextColor;
}

ColorAttribute &
ParallelCoordinatesAttributes::GetContextColor()
{
    return contextColor;
}

bool
ParallelCoordinatesAttributes::GetDrawLinesOnlyIfExtentsOn() const
{
    return drawLinesOnlyIfExtentsOn;
}

bool
ParallelCoordinatesAttributes::GetUnifyAxisExtents() const
{
    return unifyAxisExtents;
}

int
ParallelCoordinatesAttributes::GetLinesNumPartitions() const
{
    return linesNumPartitions;
}

float
ParallelCoordinatesAttributes::GetFocusGamma() const
{
    return focusGamma;
}

ParallelCoordinatesAttributes::FocusRendering
ParallelCoordinatesAttributes::GetDrawFocusAs() const
{
    return FocusRendering(drawFocusAs);
}

///////////////////////////////////////////////////////////////////////////////
// Select property methods
///////////////////////////////////////////////////////////////////////////////

void
ParallelCoordinatesAttributes::SelectScalarAxisNames()
{
    Select(ID_scalarAxisNames, (void *)&scalarAxisNames);
}

void
ParallelCoordinatesAttributes::SelectVisualAxisNames()
{
    Select(ID_visualAxisNames, (void *)&visualAxisNames);
}

void
ParallelCoordinatesAttributes::SelectExtentMinima()
{
    Select(ID_extentMinima, (void *)&extentMinima);
}

void
ParallelCoordinatesAttributes::SelectExtentMaxima()
{
    Select(ID_extentMaxima, (void *)&extentMaxima);
}

void
ParallelCoordinatesAttributes::SelectLinesColor()
{
    Select(ID_linesColor, (void *)&linesColor);
}

void
ParallelCoordinatesAttributes::SelectContextColor()
{
    Select(ID_contextColor, (void *)&contextColor);
}

///////////////////////////////////////////////////////////////////////////////
// Keyframing methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::GetFieldName
//
// Purpose:
//   This method returns the name of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

std::string
ParallelCoordinatesAttributes::GetFieldName(int index) const
{
    switch (index)
    {
    case ID_scalarAxisNames:          return "scalarAxisNames";
    case ID_visualAxisNames:          return "visualAxisNames";
    case ID_extentMinima:             return "extentMinima";
    case ID_extentMaxima:             return "extentMaxima";
    case ID_drawLines:                return "drawLines";
    case ID_linesColor:               return "linesColor";
    case ID_drawContext:              return "drawContext";
    case ID_contextGamma:             return "contextGamma";
    case ID_contextNumPartitions:     return "contextNumPartitions";
    case ID_contextColor:             return "contextColor";
    case ID_drawLinesOnlyIfExtentsOn: return "drawLinesOnlyIfExtentsOn";
    case ID_unifyAxisExtents:         return "unifyAxisExtents";
    case ID_linesNumPartitions:       return "linesNumPartitions";
    case ID_focusGamma:               return "focusGamma";
    case ID_drawFocusAs:              return "drawFocusAs";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::GetFieldType
//
// Purpose:
//   This method returns the type of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeGroup::FieldType
ParallelCoordinatesAttributes::GetFieldType(int index) const
{
    switch (index)
    {
    case ID_scalarAxisNames:          return FieldType_stringVector;
    case ID_visualAxisNames:          return FieldType_stringVector;
    case ID_extentMinima:             return FieldType_doubleVector;
    case ID_extentMaxima:             return FieldType_doubleVector;
    case ID_drawLines:                return FieldType_bool;
    case ID_linesColor:               return FieldType_color;
    case ID_drawContext:              return FieldType_bool;
    case ID_contextGamma:             return FieldType_float;
    case ID_contextNumPartitions:     return FieldType_int;
    case ID_contextColor:             return FieldType_color;
    case ID_drawLinesOnlyIfExtentsOn: return FieldType_bool;
    case ID_unifyAxisExtents:         return FieldType_bool;
    case ID_linesNumPartitions:       return FieldType_int;
    case ID_focusGamma:               return FieldType_float;
    case ID_drawFocusAs:              return FieldType_enum;
    default:  return FieldType_unknown;
    }
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::GetFieldTypeName
//
// Purpose:
//   This method returns the name of a field type given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

std::string
ParallelCoordinatesAttributes::GetFieldTypeName(int index) const
{
    switch (index)
    {
    case ID_scalarAxisNames:          return "stringVector";
    case ID_visualAxisNames:          return "stringVector";
    case ID_extentMinima:             return "doubleVector";
    case ID_extentMaxima:             return "doubleVector";
    case ID_drawLines:                return "bool";
    case ID_linesColor:               return "color";
    case ID_drawContext:              return "bool";
    case ID_contextGamma:             return "float";
    case ID_contextNumPartitions:     return "int";
    case ID_contextColor:             return "color";
    case ID_drawLinesOnlyIfExtentsOn: return "bool";
    case ID_unifyAxisExtents:         return "bool";
    case ID_linesNumPartitions:       return "int";
    case ID_focusGamma:               return "float";
    case ID_drawFocusAs:              return "enum";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::FieldsEqual
//
// Purpose:
//   This method compares two fields and return true if they are equal.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
ParallelCoordinatesAttributes::FieldsEqual(int index_, const AttributeGroup *rhs) const
{
    const ParallelCoordinatesAttributes &obj = *((const ParallelCoordinatesAttributes*)rhs);
    bool retval = false;
    switch (index_)
    {
    case ID_scalarAxisNames:
        {  // new scope
        retval = (scalarAxisNames == obj.scalarAxisNames);
        }
        break;
    case ID_visualAxisNames:
        {  // new scope
        retval = (visualAxisNames == obj.visualAxisNames);
        }
        break;
    case ID_extentMinima:
        {  // new scope
        retval = (extentMinima == obj.extentMinima);
        }
        break;
    case ID_extentMaxima:
        {  // new scope
        retval = (extentMaxima == obj.extentMaxima);
        }
        break;
    case ID_drawLines:
        {  // new scope
        retval = (drawLines == obj.drawLines);
        }
        break;
    case ID_linesColor:
        {  // new scope
        retval = (linesColor == obj.linesColor);
        }
        break;
    case ID_drawContext:
        {  // new scope
        retval = (drawContext == obj.drawContext);
        }
        break;
    case ID_contextGamma:
        {  // new scope
        retval = (contextGamma == obj.contextGamma);
        }
        break;
    case ID_contextNumPartitions:
        {  // new scope
        retval = (contextNumPartitions == obj.contextNumPartitions);
        }
        break;
    case ID_contextColor:
        {  // new scope
        retval = (contextColor == obj.contextColor);
        }
        break;
    case ID_drawLinesOnlyIfExtentsOn:
        {  // new scope
        retval = (drawLinesOnlyIfExtentsOn == obj.drawLinesOnlyIfExtentsOn);
        }
        break;
    case ID_unifyAxisExtents:
        {  // new scope
        retval = (unifyAxisExtents == obj.unifyAxisExtents);
        }
        break;
    case ID_linesNumPartitions:
        {  // new scope
        retval = (linesNumPartitions == obj.linesNumPartitions);
        }
        break;
    case ID_focusGamma:
        {  // new scope
        retval = (focusGamma == obj.focusGamma);
        }
        break;
    case ID_drawFocusAs:
        {  // new scope
        retval = (drawFocusAs == obj.drawFocusAs);
        }
        break;
    default: retval = false;
    }

    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// User-defined methods.
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::InsertAxis
//
// Purpose: Inserts an axis (assuming at the end)
//
// Programmer: Jeremy Meredith
// Creation:   January 31, 2008
//
// Note: Taken largely from Mark Blair's Parallel Axis plot.
//
// Modifications:
//    Jeremy Meredith, Fri Feb  1 17:55:14 EST 2008
//    Made it use float min/max for non-limiting extents values.
//
//    Jeremy Meredith, Mon Feb  4 16:07:37 EST 2008
//    Remove the axis extents; they were unusued.
//
//    Jeremy Meredith, Fri Feb 15 13:16:46 EST 2008
//    Renamed orderedAxisNames to scalarAxisNames to distinguish these
//    as names of actual scalars instead of just display names.  Added
//    visualAxisNames.
//
// ****************************************************************************

void
ParallelCoordinatesAttributes::InsertAxis(const std::string &axisName_)
{
    std::string newAxisName = axisName_;

    size_t curAxisCount = scalarAxisNames.size();
    size_t axisOrdinal;
    double saveExtentMin, saveExtentMax;

    stringVector::iterator saxisNamesIt;
    stringVector::iterator vaxisNamesIt;
    doubleVector::iterator extentMinIt;
    doubleVector::iterator extentMaxIt;

    for (axisOrdinal = 0; axisOrdinal < curAxisCount; axisOrdinal++)
    {
        if (scalarAxisNames[axisOrdinal] == newAxisName) break;
    }

    if (axisOrdinal < curAxisCount)
    {
        saveExtentMin  = extentMinima[axisOrdinal];
        saveExtentMax  = extentMaxima[axisOrdinal];

        saxisNamesIt = scalarAxisNames.begin()  + axisOrdinal;
        vaxisNamesIt = visualAxisNames.begin()  + axisOrdinal;
        extentMinIt  = extentMinima.begin()     + axisOrdinal;
        extentMaxIt  = extentMaxima.begin()     + axisOrdinal;

        scalarAxisNames.erase(saxisNamesIt);
        visualAxisNames.erase(vaxisNamesIt);
        extentMinima.erase(extentMinIt);
        extentMaxima.erase(extentMaxIt);
    }
    else
    {
        saveExtentMin  = -1e+37;
        saveExtentMax  = +1e+37;
    }

    size_t insertOrdinal = scalarAxisNames.size();

    saxisNamesIt = scalarAxisNames.begin()  + insertOrdinal;
    vaxisNamesIt = visualAxisNames.begin()  + insertOrdinal;
    extentMinIt  = extentMinima.begin()     + insertOrdinal;
    extentMaxIt  = extentMaxima.begin()     + insertOrdinal;

    scalarAxisNames.insert(saxisNamesIt, newAxisName);
    visualAxisNames.insert(vaxisNamesIt, newAxisName);
    extentMinima.insert(extentMinIt, saveExtentMin);
    extentMaxima.insert(extentMaxIt, saveExtentMax);

    SelectAll();
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::DeleteAxis
//
// Purpose: Deletes an axis (as long as there are enough remaining)
//
// Programmer: Jeremy Meredith
// Creation:   January 31, 2008
//
// Note: Taken largely from Mark Blair's Parallel Axis plot.
//
// Modifications:
//    Jeremy Meredith, Mon Feb  4 16:07:37 EST 2008
//    Remove the axis extents; they were unusued.
//
//    Jeremy Meredith, Fri Feb 15 13:16:46 EST 2008
//    Renamed orderedAxisNames to scalarAxisNames to distinguish these
//    as names of actual scalars instead of just display names.  Added
//    visualAxisNames.
//
//    Kathleen Bonnell, Wed Jun 4 07:54:16 PDT 2008
//    Removed unused variables leftSelectedAxisID, rightSelectedAxisID.
//
// ****************************************************************************

void
ParallelCoordinatesAttributes::DeleteAxis(const std::string &axisName_,
                                          int minAxisCount)
{
    if ((int)scalarAxisNames.size() <= minAxisCount) return;

    std::string newAxisName = axisName_;

    size_t curAxisCount = scalarAxisNames.size();
    size_t axisOrdinal;

    for (axisOrdinal = 0; axisOrdinal < curAxisCount; axisOrdinal++)
    {
        if (scalarAxisNames[axisOrdinal] == newAxisName) break;
    }

    if (axisOrdinal < curAxisCount)
    {
        visualAxisNames.erase(visualAxisNames.begin() + axisOrdinal);
        scalarAxisNames.erase(scalarAxisNames.begin() + axisOrdinal);
        extentMinima.erase(extentMinima.begin() + axisOrdinal);
        extentMaxima.erase(extentMaxima.begin() + axisOrdinal);

        SelectAll();
    }
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::AttributesAreConsistent
//
// Purpose: Returns true only if (1) all vector attributes are the same length,
//          (2) all axis names are unique, and (3) the index of the currently
//          displayable axis information in the GUI is in range.
//
// Programmer: Jeremy Meredith
// Creation:   January 31, 2008
//
// Note: Taken largely from Mark Blair's Parallel Axis plot.
//
// Modifications:
//    Jeremy Meredith, Mon Feb  4 16:07:37 EST 2008
//    Remove the axis extents; they were unusued.
//
//    Jeremy Meredith, Thu Feb  7 17:45:11 EST 2008
//    Allow empty axis name list; this happens for array variables.
//
//    Jeremy Meredith, Fri Feb 15 13:16:46 EST 2008
//    Renamed orderedAxisNames to scalarAxisNames to distinguish these
//    as names of actual scalars instead of just display names.  Added
//    visualAxisNames.
//
// ****************************************************************************

bool
ParallelCoordinatesAttributes::AttributesAreConsistent() const
{
    size_t axisNamesSize = scalarAxisNames.size();
    size_t axisNum, axis2Num;
    std::string axisName;

    if (axisNamesSize == 0)
    {
        if (extentMinima.size() != extentMaxima.size())
            return false;

        return true;
    }

    if (axisNamesSize == 1)
        return false;

    if ((extentMinima.size()     != axisNamesSize) ||
        (extentMaxima.size()     != axisNamesSize))
    {
        return false;
    }

    for (axisNum = 0; axisNum < axisNamesSize - 1; axisNum++)
    {
        axisName = scalarAxisNames[axisNum];

        for (axis2Num = axisNum + 1; axis2Num < axisNamesSize; axis2Num++ )
        {
            if (scalarAxisNames[axis2Num] == axisName)
                return false;
        }
    }

    return true;
}

// ****************************************************************************
// Method: ParallelCoordinatesAttributes::ChangesRequireRecalculation
//
// Purpose: Sets the attributes from another attribute group
//
// Programmer: Jeremy Meredith
// Creation:   January 31, 2008
//
// Modifications:
//    Jeremy Meredith, Fri Feb  8 12:35:47 EST 2008
//    Added unifyAxisExtents.
//
//    Jeremy Meredith, Fri Feb 15 13:16:46 EST 2008
//    Renamed orderedAxisNames to scalarAxisNames to distinguish these
//    as names of actual scalars instead of just display names.  Added
//    visualAxisNames (though visualnames not matching will not force
//    recalculation.)
//
//    Jeremy Meredith, Tue Mar  4 18:17:13 EST 2008
//    Added linesNumPartitions.
//
//    Jeremy Meredith, Fri Mar  7 11:43:37 EST 2008
//    Added named selection and time iteration fields.
//
//    Jeremy Meredith, Thu Mar 27 16:38:18 EDT 2008
//    Allow user to force into the mode using individual data point lines
//    for the focus instead of using a histogram.
//
//    Jeremy Meredith, Wed Feb 25 16:55:12 EST 2009
//    Port to trunk.  Removed time iteration (for now) and
//    named selections (since they are done differently now).
//
//    Jeremy Meredith, Fri Apr 24 15:36:05 EDT 2009
//    Changed focus drawing method to be an enum.  Added focus gamma.
//
// ****************************************************************************
bool
ParallelCoordinatesAttributes::ChangesRequireRecalculation(
    const ParallelCoordinatesAttributes &obj)
{
    if (extentMinima != obj.extentMinima ||
        extentMaxima != obj.extentMaxima ||
        drawLines != obj.drawLines ||
        linesNumPartitions != obj.linesNumPartitions ||
        drawContext != obj.drawContext ||
        drawLinesOnlyIfExtentsOn != obj.drawLinesOnlyIfExtentsOn ||
        contextNumPartitions != obj.contextNumPartitions ||
        contextGamma != obj.contextGamma ||
        focusGamma != obj.focusGamma ||
        scalarAxisNames != obj.scalarAxisNames ||
        unifyAxisExtents != obj.unifyAxisExtents ||
        drawFocusAs != obj.drawFocusAs
        )
    {
        return true;
    }
    return false;
}

// ****************************************************************************
//  Method:  ParallelCoordinatesAttributes::ResetAxes
//
//  Purpose:
//    Clear out all the variable axes.
//
//  Arguments:
//    none
//
//  Programmer:  Jeremy Meredith
//  Creation:    February  7, 2008
//
//  Modifications:
//    Jeremy Meredith, Fri Feb 15 13:16:46 EST 2008
//    Renamed orderedAxisNames to scalarAxisNames to distinguish these
//    as names of actual scalars instead of just display names.  Added
//    visualAxisNames.
//
// ****************************************************************************
void
ParallelCoordinatesAttributes::ResetAxes()
{
    scalarAxisNames.clear();
    visualAxisNames.clear();
    extentMinima.clear();
    extentMaxima.clear();

    SelectAll();
}

